﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using PhoneCore.Framework;
using PhoneCore.Framework.Configuration;
using PhoneCore.Framework.Diagnostic.Tracing;
using PhoneCore.Framework.IoC;
using PhoneCore.Framework.Views.Command;
using SecureBox.Tools;
using SecureBox.UI.Infrastructure.Data;
using Template = SecureBox.UI.Infrastructure.Model.Template;
using Record = SecureBox.UI.Infrastructure.Model.Record;
using Property = SecureBox.UI.Infrastructure.Model.Property;
using Keyword = SecureBox.UI.Infrastructure.Model.Keyword;

namespace SecureBox.UI.ViewModel
{
    /// <summary>
    /// Provides the base functionality for template's view model
    /// </summary>
    public abstract class TemplateViewPage: ViewModelBase 
    {
        [Dependency]
        public IDataContextService DataContextService { get; set; }

        [Dependency]
        public IPasswordGenerator PasswordGenerator { get; set; }

        public TemplateViewPage()
        {
            SaveCommand = new ExecuteCommand(OnSaveCommand);
            CancelCommand = new ExecuteCommand(OnCancelCommand);
        }

        /// <summary>
        /// Update existing record
        /// </summary>
        private void UpdateRecord()
        {
            Record r = CreateRecord();
            r.Id = EditRecord.Id;
            DataContextService.Records.Update(r);
            DataContextService.Commit();
        }

        /// <summary>
        /// Adds new record
        /// </summary>
        private void AddRecord()
        {
            Record r = CreateRecord();
            DataContextService.Records.Add(r);
            DataContextService.Commit();
        }

        /// <summary>
        /// Return properties of template
        /// </summary>
        /// <returns></returns>
        protected abstract IEnumerable<Property> GetProperties();

        /// <summary>
        /// Returns template name
        /// </summary>
        /// <returns></returns>
        protected abstract string GetTemplateName();

        /// <summary>
        /// Checks whether properties are valid
        /// </summary>
        /// <returns></returns>
        protected virtual bool IsValid()
        {
            //check default properties
            return !String.IsNullOrEmpty(Name) && !String.IsNullOrEmpty(Keyword);
        }

        /// <summary>
        /// Fill properties with values of edited record
        /// </summary>
        protected abstract void FillProperties();

        /// <summary>
        /// Erase properties with values of edited record
        /// </summary>
        protected abstract void EraseProperties();
        
        /// <summary>
        /// Creates record using data provided by user
        /// </summary>
        /// <returns></returns>
        protected  Record CreateRecord()
        {
            //get template
            Template password = DataContextService.Templates.Get(t => t.Name == GetTemplateName());
            return new Record()
            {
                CreationDate = DateTime.Now,
                Name = Name,
                Properties = GetProperties(),
                Keywords = GetKeywordsFromField(),
                Template = password
            };
        }

        /// <summary>
        /// Returns keywords
        /// </summary>
        /// <returns></returns>
        protected IEnumerable<Keyword> GetKeywordsFromField()
        {
            return Keyword.Split(',').Select(s => new Keyword() {Name = s});
        }

        /// <summary>
        /// Get property value by name
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        protected string GetPropertyValueByName(string name)
        {
            return EditRecord.Properties.Single(p => p.Name == name).Value;
        }

        /// <summary>
        /// Get keywords field value
        /// </summary>
        /// <returns></returns>
        protected string GetKeywordsField()
        {
            return string.Join(",", EditRecord.Keywords.Select(k => k.Name));
        }

        /// <summary>
        /// Name of record
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Keywords related to the template
        /// </summary>
        public string Keyword { get; set; }

        /// <summary>
        /// True, if template is openned for editing
        /// </summary>
        protected bool IsEditMode { get; set; }

        /// <summary>
        /// Contains edited record if IsEditMode is true
        /// </summary>
        protected Record EditRecord { get; set; }

        #region Command properties

        /// <summary>
        /// Command for save button click
        /// </summary>
        public ExecuteCommand SaveCommand
        {
            get;
            private set;
        }

        /// <summary>
        /// Command for cancel click
        /// </summary>
        public ExecuteCommand CancelCommand
        {
            get;
            private set;
        }

        #endregion

        #region Command handlers

        /// <summary>
        /// Saves the record in data base
        /// </summary>
        public void OnSaveCommand()
        {
            if (!IsValid())
            {
                MessageBox.Show("Please fill all properties or click cancel!");
                return;
            }
            if (IsEditMode)
                UpdateRecord();
            else
                AddRecord();
            IsEditMode = false;

            NavigationService.GoBack();
        }

        /// <summary>
        /// Cancels action
        /// </summary>
        public void OnCancelCommand()
        {
            NavigationService.GoBack();
            IsEditMode = false;
        }
        #endregion

        /// <summary>
        /// Checks navigation parameters
        /// </summary>
        protected override void ReadNavigationParameters()
        {
            //toggle edit mode if RecordId is set
            if (NavigationParameters.Keys.Contains("RecordId"))
            {
                int editRecordId = (int)NavigationParameters["RecordId"];
                EditRecord = DataContextService.Records.Get(r => r.Id == editRecordId);
                IsEditMode = true;
                FillProperties();
            }
            else
            {
                IsEditMode = false;
                EraseProperties();
            }
        }
    }
}
